package BookFiles
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.GradientType;
    import flash.display.Graphics;
    import flash.display.Shape;
    import flash.display.SpreadMethod;
    import flash.events.TimerEvent;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.utils.Timer;
    import flash.utils.getTimer;

    import mx.collections.ArrayCollection;
    import mx.core.UIComponent;
    import mx.core.UIComponentCachePolicy;
    import mx.utils.ObjectUtil;

    [DefaultProperty("content")]
    public class Book extends UIComponent
    {
        public var sheetsNumber:Number;
        private var _content:ArrayCollection;
        private var _currentSheet:BookSheet;
        private var _frontTurningSheet:BookSheet;
        private var _backTurningSheet:BookSheet
        private var _frontTurningBitmap:BitmapData;
        private var _backTurningBitmap:BitmapData;
        private var _leftPageStackBitmap:Bitmap;
        private var _rightPageStackBitmap:Bitmap;

        private var _flipLayer:Shape;

        //flags
        private var _startTurn:Boolean = true;

        private var dragAlpha:Number = 0;
        private var grabAlpha:Number = 0;
        private var _turnDirection:Number = TURN_DIRECTION_FORWARD;
        private var _timer:Timer;
        private var _turnStartTime:Number;
        private var _turnDuration:Number = 1000;
        //
        private var _state:String = "STATIC";
        private var _currentSheetIndex:Number = 0;
        private var _futureSheetIndex:Number;
        // cached calculated page dimensions
        private var _pageWidth:Number;
        private var _pageHeight:Number;
        private var _hCenter:Number;
        private var _pageLeft:Number;
        private var _pageTop:Number;
        private var _pageRight:Number;
        private var _pageBottom:Number;
        private var _oldWidth:Number;
        private var _oldHeight:Number;

        public static const TURN_DIRECTION_FORWARD:Number = 0;
        public static const TURN_DIRECTION_BACKWARDS:Number = 1;



        public function Book()
        {
            _timer = new Timer(10);
            _timer.addEventListener(TimerEvent.TIMER, timerHandler);
        }

        public function set content(value:Array):void
        {
            if (value && value is Array)
            {
                _content = new ArrayCollection(value);
                invalidateProperties();
            }
        }

        public function set currentSheetIndex(value:Number):void
        {
            _currentSheetIndex = value;
            invalidateProperties();
        }

        public function get currentSheetIndex():Number
        {
            return _currentSheetIndex;
        }

//add current sheet and layer for curve page effect
        override protected function createChildren():void
        {
            _flipLayer = new Shape();

            _frontTurningSheet = new BookSheet;
            _backTurningSheet = new BookSheet;
            _frontTurningSheet.cachePolicy = UIComponentCachePolicy.ON;
            _backTurningSheet.cachePolicy = UIComponentCachePolicy.ON;
            _frontTurningSheet.styleName = this;
            _backTurningSheet.styleName = this;
            addChild(_frontTurningSheet);
            addChild(_backTurningSheet);
            _frontTurningSheet.visible = false;
            _backTurningSheet.visible = false;
            //I want to note that these sheets will never be visible

            _leftPageStackBitmap = new Bitmap();
            addChild(_leftPageStackBitmap);
            _rightPageStackBitmap = new Bitmap();
            addChild(_rightPageStackBitmap);

            _currentSheet = new BookSheet();
            _currentSheet.styleName = this;
            _currentSheet.cacheAsBitmap = true;
            addChild(_currentSheet);
            addChild(_flipLayer);
        }

//clean pages of current sheet nad fill new pages
        override protected function commitProperties():void
        {
            //clean block
            if (_content == null)
                return;
            _currentSheet.clearContent();

            _frontTurningSheet.clearContent();
            _frontTurningBitmap = null;
            _backTurningSheet.clearContent();
            _backTurningBitmap = null;

            _leftPageStackBitmap.bitmapData = null;
            _rightPageStackBitmap.bitmapData = null;

            //filling in block
            if (_state == "STATIC")
            {
                _currentSheet.visible = true;
                fillSheet(_currentSheet, _currentSheetIndex);
            }

            if (_state == "TURN")
            {
                _currentSheet.visible = false;
                if (_turnDirection == TURN_DIRECTION_FORWARD)
                {
                    fillSheet(_frontTurningSheet, _currentSheetIndex);
                    fillSheet(_backTurningSheet, _currentSheetIndex + 1);
                }
                else
                {
                    fillSheet(_frontTurningSheet, _currentSheetIndex);
                    fillSheet(_backTurningSheet, _currentSheetIndex - 1);
                }
            }

            //pass the tern to updateDisplayList
            invalidateDisplayList();
        }

        private function fillSheet(page:BookSheet, pageIndex:Number):void
        {
            var contentIndex:Number = pageIndex * 2;
            if (contentIndex == 0)
            {
                page.leftPage = null;
                page.rightPage = _content[contentIndex];
            }
            if (contentIndex >= 2 && contentIndex < _content.length)
            {
                page.leftPage = _content[contentIndex - 1];
                page.rightPage = _content[contentIndex];

            }

            if (contentIndex == _content.length)
            {
                page.leftPage = _content[contentIndex - 1];
                page.rightPage = null;
            }
        }

        private function updateDetails():void
        {
            _hCenter = unscaledWidth / 2;
            _pageWidth = unscaledWidth / 2;
            _pageLeft = _hCenter - _pageWidth;
            _pageRight = _hCenter + _pageWidth;
            _pageTop = 0;
            _pageBottom = unscaledHeight;
            _pageHeight = unscaledHeight;
            _oldWidth = unscaledWidth;
            _oldHeight = unscaledHeight;
        }

// set sizes and curve effect of static pages
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            if (_oldWidth != unscaledWidth || _oldHeight != unscaledHeight)
            {
                updateDetails();
            }
            if (_state == "STATIC")
            {
                _currentSheet.setActualSize(2 * _pageWidth, _pageHeight);
                _currentSheet.move(_pageLeft, _pageTop);
            }

            if (_state == "TURN")
            {
                if (_turnDirection == TURN_DIRECTION_FORWARD)
                {
                    _frontTurningSheet.setActualSize(2 * _pageWidth, _pageHeight);
                    if (_frontTurningSheet is UIComponent && UIComponent(_frontTurningSheet).initialized == false)
                        UIComponent(_frontTurningSheet).initialized = true;
                    _frontTurningBitmap = new BitmapData(_pageWidth, _pageHeight, true, 0);
                    _frontTurningSheet.copyInto(_frontTurningBitmap, "right");

                    _backTurningSheet.setActualSize(2 * _pageWidth, _pageHeight);
                    if (_backTurningSheet is UIComponent && UIComponent(_backTurningSheet).initialized == false)
                        UIComponent(_backTurningSheet).initialized = true;
                    _backTurningBitmap = new BitmapData(_pageWidth, _pageHeight, true, 0);
                    _backTurningSheet.copyInto(_backTurningBitmap, "left");
                }
                else
                {
                    _frontTurningSheet.setActualSize(2 * _pageWidth, _pageHeight);
                    if (_frontTurningSheet is UIComponent && UIComponent(_frontTurningSheet).initialized == false)
                        UIComponent(_frontTurningSheet).initialized = true;
                    _frontTurningBitmap = new BitmapData(_pageWidth, _pageHeight, true, 0);
                    _frontTurningSheet.copyInto(_frontTurningBitmap, "left");

                    _backTurningSheet.setActualSize(2 * _pageWidth, _pageHeight);
                    if (_backTurningSheet is UIComponent && UIComponent(_backTurningSheet).initialized == false)
                        UIComponent(_backTurningSheet).initialized = true;
                    _backTurningBitmap = new BitmapData(_pageWidth, _pageHeight, true, 0);
                    _backTurningSheet.copyInto(_backTurningBitmap, "right");


                }



                _leftPageStackBitmap.bitmapData = new BitmapData(2 * _pageWidth, _pageHeight, true, 0);
                if (_turnDirection == TURN_DIRECTION_FORWARD)
                {
                    _frontTurningSheet.copyInto(_leftPageStackBitmap.bitmapData, "left");
                }
                else
                {
                    _backTurningSheet.copyInto(_leftPageStackBitmap.bitmapData, "left");
                }

                _rightPageStackBitmap.bitmapData = new BitmapData(2 * _pageWidth, _pageHeight, true, 0);
                if (_turnDirection == TURN_DIRECTION_FORWARD)
                {
                    _backTurningSheet.copyInto(_rightPageStackBitmap.bitmapData, "right");
                }
                else
                {
                    _frontTurningSheet.copyInto(_rightPageStackBitmap.bitmapData, "right");
                }

                _leftPageStackBitmap.x = _pageLeft;
                _leftPageStackBitmap.y = _pageTop;
                _rightPageStackBitmap.x = _pageLeft;
                _rightPageStackBitmap.y = _pageTop;

            }


            var g:Graphics = _flipLayer.graphics;
            g.clear();

            drawPageSlopes();
            //dragAlpha:Number = 0.8 * Math.PI;
            //grabAlhpa:Number = 0;
            if (_state == "TURN")
            {

                //turnPage(dragAlpha, grabAlpha);
                turnSoftPage(dragAlpha, grabAlpha);
            }

        }


//page slope effect (curve of page) update display list imvoke this function
        private function drawPageSlopes():void
        {
            var g:Graphics = _flipLayer.graphics;

            var m:Matrix = new Matrix();
            if (_currentSheetIndex < sheetsNumber - 1)
            {
                m.createGradientBox(_pageWidth, _pageHeight, 0, _hCenter, _pageTop);
                g.lineStyle(0, 0, 0);
                g.moveTo(_hCenter, _pageTop);
                beginRightSideGradient(g, m);
                g.lineTo(_pageRight, _pageTop);
                g.lineTo(_pageRight, _pageBottom);
                g.lineTo(_hCenter, _pageBottom);
                g.lineTo(_hCenter, 0);
                g.endFill();
            }
            if (_currentSheetIndex > 0)
            {
                m.createGradientBox(_pageWidth, _pageHeight, Math.PI, _pageLeft, _pageTop);
                g.lineStyle(0, 0, 0);
                g.moveTo(_hCenter, _pageTop);

                beginLeftSideGradient(g, m);
                g.lineTo(_pageLeft, _pageTop);
                g.lineTo(_pageLeft, _pageBottom);
                g.lineTo(_hCenter, _pageBottom);
                g.lineTo(_hCenter, _pageTop);
                g.endFill();
            }
        }



        private function beginRightSideGradient(g:Graphics, m:Matrix, isStiff:Boolean = false):void
        {
            g.beginGradientFill(GradientType.LINEAR, [0, 0xFFFFFF], [0.27, 0], [0, 86], m);
        }

        private function beginLeftSideGradient(g:Graphics, m:Matrix, isStiff:Boolean = false):void
        {
            g.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0], [0.19, 0], [0, 100], m, SpreadMethod.PAD);
        }

        private function beginFrontGradient(g:Graphics, m:Matrix):void
        {
            g.beginGradientFill(GradientType.LINEAR, [0, 0], [0.9, 0.00], [0, 150], m, SpreadMethod.PAD);

        }

        private function beginShadowOnRevealedPage(g:Graphics, m:Matrix, p:Number):void
        {
            g.beginGradientFill(GradientType.LINEAR, [0, 0], [1.8 * (1 - p), 0], [0, 210], m);
        }

        private function begindUndersideCurveGradient(g:Graphics, m:Matrix, p:Number):void
        {

            g.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0], [0.9, 0], [0, 240], m, SpreadMethod.PAD);
        }

        private function turnPage(dragAngle:Number, grabAngle:Number):void
        {

            var hasLeftContent:Number = 0;
            var hasRightContent:Number = 1;


            /*var ellipseHAxis:Number = Math.abs(grabPt.x - _hCenter);
               var ellipseVAxis:Number = (_pageWidth / 4) * (ellipseHAxis / _pageWidth);
               var slope:Number = -(dragPt.y - grabPt.y) / (dragPt.x - _hCenter);
               var eqY:Number = Math.sqrt((slope * ellipseHAxis * ellipseVAxis) * (slope * ellipseHAxis * ellipseVAxis) / (ellipseVAxis * ellipseVAxis + slope * slope * ellipseHAxis * ellipseHAxis));
               var eqX:Number = ellipseHAxis * Math.sqrt(1 - (eqY * eqY) / (ellipseVAxis * ellipseVAxis));

               var targetGrabX:Number = _hCenter + ((dragPt.x > _hCenter) ? eqX : -eqX);
               var targetGrabY:Number = grabPt.y - eqY;


               var adjustedDragPt:Point = dragPt.clone();
               if (_turnDirection == TURN_DIRECTION_FORWARD)
               {
               adjustedDragPt.x = Math.min(grabPt.x, adjustedDragPt.x);
               adjustedDragPt.x = Math.max(_hCenter - (grabPt.x - _hCenter), adjustedDragPt.x);
               hPageEdge = _pageRight;
               }
               else
               {
               adjustedDragPt.x = Math.max(grabPt.x, adjustedDragPt.x);
               adjustedDragPt.x = Math.min(_hCenter + (_hCenter - grabPt.x), adjustedDragPt.x);
               hPageEdge = _pageLeft;
               }
               var ellipseYIntersection:Number = ellipseVAxis * Math.sqrt(1 - Math.pow((adjustedDragPt.x - _hCenter) / ellipseHAxis, 2));
               topCorner = new Point(hPageEdge, _pageTop);
               bottomCorner = new Point(hPageEdge, _pageBottom);


             var scale:Number = Math.abs((adjustedDragPt.x - _hCenter) / (grabPt.x - _hCenter));*/
            var bigEllipseSemiAxis:Number = _pageWidth;
            var smallEllipseSemiAxis:Number = _pageHeight / 5;
            var xAlpha:Number = 1 / Math.sqrt(Math.cos(dragAngle) * Math.cos(dragAngle) / bigEllipseSemiAxis / bigEllipseSemiAxis + Math.sin(dragAngle) * Math.sin(dragAngle) / smallEllipseSemiAxis / smallEllipseSemiAxis) *
                Math.cos(dragAngle);
            var yAlpha:Number = 1 / Math.sqrt(Math.cos(dragAngle) * Math.cos(dragAngle) / bigEllipseSemiAxis / bigEllipseSemiAxis + Math.sin(dragAngle) * Math.sin(dragAngle) / smallEllipseSemiAxis / smallEllipseSemiAxis) *
                Math.sin(dragAngle);
            var xAdjusted:Number = _pageWidth + xAlpha;
            var yAdjusted:Number = _pageHeight - yAlpha;
            var adjustedDragPt:Point = new Point(xAdjusted, yAdjusted);
            var scale:Number = Math.abs(xAlpha) / _pageWidth;
            var slope:Number = Math.tan(dragAngle);
            slope = Math.abs(yAlpha) / Math.abs(xAlpha);


            var m:Matrix = new Matrix();
            var g:Graphics = _flipLayer.graphics;
            g.lineStyle(0, 0, 0);

            if (adjustedDragPt.x > _hCenter)
            {
                m.identity();
                m.scale(scale, 1);
                //m.b = -ellipseYIntersection / Math.abs(grabPt.x - _hCenter);
                m.b = -slope * scale;
                m.translate(_hCenter, _pageTop);
            }
            else
            {
                m.identity();
                m.scale(scale, 1);
                m.b = slope * scale;
                //m.b = ellipseYIntersection / Math.abs(_hCenter - grabPt.x);
                m.translate(_hCenter - _pageWidth * scale, _pageTop - yAlpha);
            }

            var bitmapTopAnchor:Point = m.transformPoint(new Point(0, 0));
            var bitmapBottomAnchor:Point = m.transformPoint(new Point(0, _pageHeight));
            var bitmapTopCorner:Point = m.transformPoint(new Point(_pageWidth, 0));
            var bitmapBottomCorner:Point = m.transformPoint(new Point(_pageWidth, _pageHeight));

            var pagePoly:Array = [bitmapTopAnchor, bitmapTopCorner, bitmapBottomCorner, bitmapBottomAnchor];

            if (Math.abs(scale * _pageWidth) > 1)
            {
                var sm:Matrix = new Matrix();
                if (adjustedDragPt.x > _hCenter)
                {
                    if (Math.abs(scale * _pageWidth) > 5)
                    {
                        sm.createGradientBox(_pageWidth * (scale * .9), _pageHeight, 0, _hCenter, _pageTop);
                        beginStiffShadowGradient(g, sm);
                        g.moveTo(_hCenter, _pageTop);
                        g.lineTo(_pageRight, _pageTop);
                        g.lineTo(_pageRight, _pageBottom);
                        g.lineTo(_hCenter, _pageBottom);
                        g.lineTo(_hCenter, _pageTop);
                        g.endFill();
                    }
                }
                else
                {
                    if (Math.abs(scale * _pageWidth) > 5)
                    {
                        sm.createGradientBox(_pageWidth * (Math.abs(scale) * .9), _pageHeight, Math.PI, _hCenter - _pageWidth * (Math.abs(scale) * .9), _pageTop);
                        beginStiffShadowGradient(g, sm);
                        g.moveTo(_pageLeft, _pageTop);
                        g.lineTo(_hCenter, _pageTop);
                        g.lineTo(_hCenter, _pageBottom);
                        g.lineTo(_pageLeft, _pageBottom);
                        g.lineTo(_pageLeft, _pageTop);
                        g.endFill();
                    }
                }


                if (adjustedDragPt.x > _hCenter)
                {
                    g.beginBitmapFill(_turnDirection == TURN_DIRECTION_FORWARD ? _frontTurningBitmap : _backTurningBitmap, m, false, true);
                }
                else
                {
                    g.beginBitmapFill(_turnDirection == TURN_DIRECTION_FORWARD ? _backTurningBitmap : _frontTurningBitmap, m, false, true);
                }
                drawPoly(g, pagePoly);
                g.endFill();

                var gm:Matrix = new Matrix();
                if (adjustedDragPt.x > _hCenter)
                {
                    gm.createGradientBox(_pageWidth * scale, _pageHeight, 0, _hCenter, _pageTop);
                    beginRightSideGradient(g, gm, true);
                }
                else
                {
                    gm.createGradientBox(_pageWidth * scale, _pageHeight, Math.PI, _hCenter - _pageWidth * scale, _pageTop);
                    beginLeftSideGradient(g, gm, true);
                }

                drawPoly(g, pagePoly);
                g.endFill();
            }


        }

        private function drawPoly(g:Graphics, poly:Array):void
        {


            //trace(poly[0].toString()+" "+poly[1].toString()+" "+poly[2].toString()+" "+poly[3].toString());


            g.moveTo(poly[0].x, poly[0].y);
            for (var i:int = 0; i < poly.length; i++)
            {
                g.lineTo(poly[i].x, poly[i].y);
            }
            g.lineTo(poly[0].x, poly[0].y);

        }

        private function beginStiffShadowGradient(g:Graphics, m:Matrix):void
        {
            g.beginGradientFill(GradientType.LINEAR, [0, 0], [2.4 * 1.4, 0], [0, 255], m);
        }

        public function startTurningPage(pageIndex:Number, direction:Number):void
        {
            if (_startTurn)
            {
                _startTurn = false;
                _turnDirection = direction;
                _timer.start();
                _turnStartTime = NaN;
                grabAlpha = 0;
                _state = "TURN";
                invalidateProperties();



            }
        }

        private function timerHandler(e:TimerEvent = null):void
        {
            if (_state == "TURN")
            {

                if (isNaN(_turnStartTime))
                    _turnStartTime = getTimer();

                var t:Number = (getTimer() - _turnStartTime) / _turnDuration;
                t = Math.min(t, 1);

                //t = 0.6

                if (_turnDirection == TURN_DIRECTION_FORWARD)
                    dragAlpha = (0.5 * Math.sin(Math.PI / 2 * (2 * t - 1)) + 0.5) * Math.PI;
                if (_turnDirection == TURN_DIRECTION_BACKWARDS)
                    dragAlpha = (0.5 * Math.cos(Math.PI * t) + 0.5) * Math.PI;


                invalidateDisplayList();
                if (t == 1)
                    finishTurn();

            }
        }

        private function finishTurn():void
        {
            _timer.stop();
            dragAlpha = 0;
            _state = "STATIC";
            _startTurn = true;
            if (_turnDirection == TURN_DIRECTION_FORWARD)
                _currentSheetIndex++;
            else
                _currentSheetIndex--;
            invalidateProperties();
        }

        private function turnSoftPage(dragAngle:Number, grabAngle:Number):void
        {

            trace(dragAngle);

            dragAngle = ObjectUtil.copy(dragAngle) as Number;
            //list of right page points
            var rightBottomPageCorner:Point = new Point(_pageRight, _pageBottom);
            var rightTopPageCorner:Point = new Point(_pageRight, _pageTop);
            var centerLineTop:Point = new Point(_hCenter, _pageTop);
            var centerLineBottom:Point = new Point(_hCenter, _pageBottom);

            //list of left page points
            var leftBottomPageCorner:Point = new Point(_pageLeft, _pageBottom);
            var leftTopPageCorner:Point = new Point(_pageLeft, _pageTop);
            centerLineTop;
            centerLineBottom;



            // list right front points
            var rightTopFront:Point;
            var rightBottomFront:Point;

            //list left front points
            var leftTopFront:Point;
            var leftBottomFront:Point;




            //calculation drag point
            var bigEllipseSemiAxis:Number = _pageWidth;
            var smallEllipseSemiAxis:Number = _pageHeight / 5;
            var xAlpha:Number = 1 / Math.sqrt(Math.cos(dragAngle) * Math.cos(dragAngle) / bigEllipseSemiAxis / bigEllipseSemiAxis + Math.sin(dragAngle) * Math.sin(dragAngle) / smallEllipseSemiAxis / smallEllipseSemiAxis) *
                Math.cos(dragAngle);
            var yAlpha:Number = 1 / Math.sqrt(Math.cos(dragAngle) * Math.cos(dragAngle) / bigEllipseSemiAxis / bigEllipseSemiAxis + Math.sin(dragAngle) * Math.sin(dragAngle) / smallEllipseSemiAxis / smallEllipseSemiAxis) *
                Math.sin(dragAngle);
            var xDragPoint:Number = _pageWidth + xAlpha;
            var yDragPoint:Number = _pageHeight - yAlpha;
            var dragPoint:Point = new Point(xDragPoint, yDragPoint);


            // rotation of  back support
            var startVectorRotation:Point;
            var endVectorRotation:Point;

            //math support
            var grabPoint:Point;
            var _currentEdge:Number;
            var currentTopPageCorner:Point;
            if (_turnDirection == TURN_DIRECTION_FORWARD)
            {
                grabPoint = rightBottomPageCorner;
                _currentEdge = _pageRight;
                currentTopPageCorner = rightTopPageCorner;
            }
            else
            {
                grabPoint = leftBottomPageCorner;
                _currentEdge = _pageLeft;
                currentTopPageCorner = leftTopPageCorner;
            }
            var ms:MathSupport = new MathSupport(dragPoint, grabPoint);
            var middlePoint:Point = ms.takeMiddle();

            //frontPoly creation
            var frontPoly:Array = [];

            frontPoly.push(centerLineTop);

            // Calculation intersection with top
            var crossingWithTop:Number = ms.xForFixedY(_pageTop);


            if (Math.abs(crossingWithTop - _hCenter) > Math.abs(_currentEdge - _hCenter))
            {
                rightTopFront = new Point(_currentEdge, ms.yForFixedX(_currentEdge));
                frontPoly.push(currentTopPageCorner);
                frontPoly.push(rightTopFront);


            }
            else
            {
                rightTopFront = new Point(crossingWithTop, _pageTop);
                frontPoly.push(rightTopFront);

            }


            rightBottomFront = new Point(ms.xForFixedY(_pageBottom), _pageBottom);
            frontPoly.push(rightBottomFront);
            frontPoly.push(centerLineBottom);

            if (dragAngle == 0)
            {
                frontPoly = [];
                frontPoly.push(centerLineTop);
                frontPoly.push(currentTopPageCorner);
                frontPoly.push(grabPoint);
                frontPoly.push(centerLineBottom);
            }

            var m:Matrix = new Matrix();

            var g:Graphics = _flipLayer.graphics;


            //draw _frontTurningBitmap
            if (_frontTurningBitmap != null)
            {
                // draw the top of the turning page
                m.identity();
                if (_turnDirection == TURN_DIRECTION_FORWARD)
                {
                    m.tx = _hCenter;
                    m.ty = _pageTop;
                    g.beginBitmapFill(_frontTurningBitmap, m, false, true);
                }
                else
                {
                    m.tx = _pageLeft;
                    m.ty = _pageTop;
                    g.beginBitmapFill(_frontTurningBitmap, m, false, true);

                }


                drawPoly(g, frontPoly);
                g.endFill();
            }
            // draw the side gradient
            if (_turnDirection == TURN_DIRECTION_FORWARD)
            {
                m.createGradientBox(_pageWidth, _pageHeight, 0, _hCenter, _pageTop);
                beginRightSideGradient(g, m);
            }
            else
            {
                m.createGradientBox(_pageWidth, _pageHeight, Math.PI, _pageLeft, _pageTop);
                beginLeftSideGradient(g, m);
            }
            drawPoly(g, frontPoly);
            g.endFill();

            //draw front gradient
            var len:Number = Math.sqrt((dragPoint.x - middlePoint.x) * (dragPoint.x - middlePoint.x) + (dragPoint.y - middlePoint.y) * (dragPoint.y - middlePoint.y)) / 2;
            if (len * 1.8 > 10)
            {
                m.identity();
                m.scale(len * 1.8 / 1638.4, 0.03);
                var angle:Number;

                if (Math.abs(crossingWithTop - _hCenter) > Math.abs(_currentEdge - _hCenter))
                {
                    angle = Math.atan(Math.abs((_currentEdge - rightBottomFront.x) / (_pageBottom - rightTopFront.y)));
                }
                else
                {
                    angle = Math.atan(Math.abs((rightTopFront.x - rightBottomFront.x) / (_pageBottom - _pageTop)));
                }

                if (_turnDirection == TURN_DIRECTION_FORWARD)
                {
                    m.rotate(Math.PI + angle);
                }
                else
                {
                    m.rotate(-angle);
                }
                m.translate((dragPoint.x + middlePoint.x) / 2, (dragPoint.y + middlePoint.y) / 2);
                beginFrontGradient(g, m);
            }
            drawPoly(g, frontPoly);
            g.endFill();


            //return;
            if (dragAngle == 0)
                return;
            //calculation of openedPoly
            var openedPoly:Array = [];

            openedPoly.push(rightTopFront);

            if (Math.abs(crossingWithTop - _hCenter) < Math.abs(_currentEdge - _hCenter))
            {
                openedPoly.push(currentTopPageCorner);

            }
            openedPoly.push(grabPoint);
            openedPoly.push(rightBottomFront);

            // draw the shadow being cast onto the revealed page

            var turnPercent:Number;

            if (_turnDirection == TURN_DIRECTION_FORWARD)
            {
                turnPercent = 1 - (dragPoint.x - _pageLeft) / (2 * _pageWidth);
            }
            else
            {
                turnPercent = (dragPoint.x - _pageLeft) / (2 * _pageWidth);
            }

            m.identity();


            if (len > 1 && ((_turnDirection == TURN_DIRECTION_FORWARD && _backTurningSheet.hasRightPage()) || (_turnDirection == TURN_DIRECTION_BACKWARDS && _backTurningSheet.hasLeftPage())))
            {
                m.scale(len / 1638.4, 0.03);
                if (_turnDirection == TURN_DIRECTION_FORWARD)
                {
                    m.rotate(angle);
                }
                else
                {
                    m.rotate(Math.PI - angle);
                }
                m.translate(middlePoint.x, middlePoint.y);
                beginShadowOnRevealedPage(g, m, turnPercent);
                drawPoly(g, openedPoly);
                g.endFill();
            }



            //backPoly creation
            var backPoly:Array = [];



            var leftTopFold:Point = ms.reflection(currentTopPageCorner);

            var yForRotation:Number = rightBottomFront.y - rightTopFront.y;
            var xForRotation:Number = rightTopFront.x - rightBottomFront.y;

            if (Math.abs(crossingWithTop - _hCenter) > Math.abs(_currentEdge - _hCenter))
            {
                backPoly.push(rightTopFront);

                startVectorRotation = new Point(0, 1);

            }
            else
            {

                backPoly.push(leftTopFold);
                backPoly.push(rightTopFront);
                startVectorRotation = new Point(1, 0);

            }
            backPoly.push(rightBottomFront);
            backPoly.push(dragPoint);

            endVectorRotation = new Point(rightTopFront.x - leftTopFold.x, rightTopFront.y - leftTopFold.y);

            var a:Number = rightTopFront.x - leftTopFold.x;
            var b:Number = _pageTop - leftTopFold.y;

            if (_backTurningBitmap != null)
            {
                // draw the underside of the turned page
                m.identity();
                var angleRotation:Number;
                if (_turnDirection == TURN_DIRECTION_FORWARD)
                {
                    angleRotation = Math.acos((startVectorRotation.x * endVectorRotation.x + startVectorRotation.y * endVectorRotation.y) / endVectorRotation.length);
                }
                else
                {
                    if (Math.abs(crossingWithTop - _hCenter) > Math.abs(_currentEdge - _hCenter))
                    {
                        angleRotation = -Math.acos((startVectorRotation.x * endVectorRotation.x + startVectorRotation.y * endVectorRotation.y) / endVectorRotation.length);
                    }
                    else
                    {

                        angleRotation = Math.acos((startVectorRotation.x * endVectorRotation.x + startVectorRotation.y * endVectorRotation.y) / endVectorRotation.length) - Math.PI;
                    }
                }
                m.rotate(angleRotation);

                m.tx = leftTopFold.x;
                m.ty = leftTopFold.y;

                g.beginBitmapFill(_backTurningBitmap, m, true, true);

                g.lineStyle(0, 0, 0);
                drawPoly(g, backPoly);
                g.endFill();
            }
            // draw the curvature gradient on the underside of the turned page


            if (len > 10)
            {
                m.identity();
                m.scale(len / 1638.4, 50 / 1638.4);
                if (_turnDirection == TURN_DIRECTION_FORWARD)
                {
                    m.rotate(Math.PI + angle);
                }
                else
                {
                    m.rotate(-angle);
                }
                m.translate(middlePoint.x, middlePoint.y);
                begindUndersideCurveGradient(g, m, turnPercent);
                drawPoly(g, backPoly);
                g.endFill();
            }


        }




    }




}